const JWT = require("../../utils/jwt");
const MYSQL = require("../../sql/mysql");
const MYSQLConfig = require("../../sql/database");
const SQLName = MYSQLConfig.datasheetName.user_token;
// 系统配置信息
const Config = require("../../config");
const DayJs = require("dayjs");
const Redis = require("../../sql/redis");

// 项目名称
const { name } = Config.system;
// token Redis 路径
let keyPath = `${name}:user:token`
// Redis 开启状态
let RedisStatus = Config.Radis.status;


/**
 *  Redis 存储 Token路径
 *  path:项目名称:user:token:用户id
 */

/**
 * Token列表
 * @param {*} userInfo
 * @returns
 */
async function TokenList(params = {}) {

    try {

        let {
            page = 1,
            limit = 10
        } = params
        // 开启Redis存储方案
        if (RedisStatus) {
            let tokenList = await Redis.get(keyPath);
            let list = tokenList

            return {
                status: true,
                code: 0, msg: "获取成功",
                data: {
                    list,
                    total,
                    pages,
                    page,
                    limit
                }
            }
        }
        // 未开启Redis存储方案,采用Mysql
        if (!RedisStatus) {
            let tokenQuerySql = `
            select * from user_token
            LIMIT ${limit} OFFSET ${(page - 1) * limit}
            `;
            let tokenList = await MYSQL.promise(SQLName, tokenQuerySql);
            let list = tokenList.map((item) => {
                let { id, user_id, secretkey, expired_date, create_date } = item;
                return {
                    id,
                    user_id,
                    secretkey,
                    expired_date,
                    create_date,
                };
            });

            // 获取token数据总数
            let totalQuerySql = `
            select count(*) as total from user_token
            `;
            let total = await MYSQL.promise(SQLName, totalQuerySql);

            return {
                status: true,
                code: 0, msg: "获取成功",
                data: {
                    list,
                    total,
                    pages,
                    page,
                    limit
                }
            }
        }

    } catch (err) {



    }




}

/**
 * 创建Token
 * @param {*} userInfo
 * @returns
 */
async function CreatedToken() {
    try {
        let SecretKeyConfig = Config.SecretKey;
        let { way } = SecretKeyConfig;
        let { user } = userInfo;
        // 密钥类型
        let secretKetType = null;
        // 密钥
        let secretKey = null;

        // 当前时间
        let now_date = DayJs(Date.now()).valueOf();
        // 密钥创建时间
        let create_date = now_date;
        // 密钥过期时间
        let expired_date = null;

        // 返回数据对象
        let returnData = {};

        if (way == "token") {
            //   token配置对象
            let tokenConfig = SecretKeyConfig.type.token;
            let { expired } = tokenConfig;
            expired_date = now_date + expired;
            let createTokenInfo = JWT.createToken(userInfo);
            let token = createTokenInfo.secretkey;
            secretKey = token;
            returnData.token = token;
            secretKetType = 0;
        } else if (way == "cookie") {
            let cookie = "tesk cookie";
            returnData.cookie = cookie;
            secretKey = cookie;
            secretKetType = 1;
        } else {
            throw {
                code: 500,
                msg: "密钥创建失败,不支持的密钥类型",
                statusCode: 500,
            };
        }
        // 删除数据库中已经过期的token记录
        await MYSQL.promise().query(
            `DELETE FROM ${SQLName} WHERE expired_date < '${create_date}' `
        );
        // 将本次生成的token存入数据库中
        await MYSQL.promise().query(`INSERT INTO ${SQLName} SET ?`, {
            type: secretKetType,
            user,
            userInfo: JSON.stringify(userInfo),
            secretKey,
            expired_date,
            create_date,
        });

        // 返回数据
        return {
            code: 0,
            msg: "操作成功",
            data: {

                secretKey,
                expired_date,
                create_date,
                ...returnData,
            },
        };
    } catch (error) {
        console.log(error);
        console.log("操作失败,创建token时发生错误 -a");
        throw error;
    }
}
/**
 * Token信息
 * @param {*} userInfo
 * @returns
 */
async function TokenInfo() {

}
/**
 * 删除token
 * @param {*} userInfo
 * @returns
 */
async function DeleteToken(token) {

    try {
        // redis删除token
        await Redis.delete(keyPath)
        await MYSQL.promise().query(
            `DELETE FROM ${SQLName} WHERE secretKey = '${token}' `
        );
    } catch (error) {

    }

}

/**
 * token 续期
 * @brief token续期将mysql数据库中的token记录的过期时间延长到指定时间,当续期成功（更新数据库后）并不会返回任何数据,当模块运行成功则表示续期成功，反之续期失败
 * @note 本模块需要传入新的续期的时间戳,并以传入的时间戳更新数据库,并不会检查新的时间戳是否是以前的时间
 * @param {object} params 需要续期的token
 * @param {string} params.token 需要续期的token
 * @param {string} params.expired 续期新的时间戳
 * @return {Promise<{code:number,msg:string} | {code:number,msg:string}>}
 */
async function RenewalToken(parmas = {}) {
    try {
        let { token, expired } = params;
        if (!token) {
            throw { code: 500, msg: "操作失败,token不能为空" };
        } else if (!expired) {
            throw { code: 500, msg: "操作失败,过期时间不能为空" };
        }
        let updateQuery = `
            UPDATE ${SQLName}
            SET 
            expired_date = '${expired}'
            WHERE token = '${token}'
        `;
        let result = await MYSQL.queryPromise(updateQuery);
        let { affectedRows } = result;
        if (affectedRows) {
            return {
                code: 0,
                msg: "续期成功",
            };
        } else {
            throw { code: 500, msg: "续期失败,未知错误" };
        }
    } catch (error) {
        console.log(error);
        throw { code: 500, msg: "操作失败,续期token发生错误" };
    }
}

/**
 * 处置所有过期的token
 * @brief 本模块将所有过期的token但token在数据库中的state并未及时更新的记录进行处理
 * @note 本模块只是更新记录操作,并不删除过期的token
 * @return {Promise<{code:number,msg:string} | {code:number,msg:string}>}
 */
async function CleanAllToken() {

    try {
        let RedisKeyPath = keyPath + "*"

        // 获取所有token
        let RedisTokenList = await Redis.keys(RedisKeyPath)


    } catch (error) {
        console.log(error)
        throw {
            code: 500,
            msg: "操作失败,清理token时发生错误"
        }

    }

}

/**
 * 清空Redis中存储的所有Token
 * @brief 本模块将所有过期的token但token在数据库中的state并未及时更新的记录进行处理
 * @note 本模块只是更新记录操作,并不删除过期的token
 * @return {Promise<{code:number,msg:string} | {code:number,msg:string}>}
 */
async function CleanAllRedisToken() {
    try {
        let keyPath = `${name}:user:token:*`
        // redis删除所有token
        await Redis.delete(keyPath)
        // 返回数据
        return {
            code: 0,
            msg: "操作成功"
        }
    } catch (err) {
        console.log(err)
        throw {
            code: 500,
            msg: "操作失败,清理token时发生错误"
        }
    }
}
// 暴露接口
module.exports = {
    CreatedToken,
    TokenList,
    TokenInfo,
    DeleteToken,
    RenewalToken,
    CleanAllToken,
    CleanAllRedisToken
};
